#include "IndicateLineItem.h"
#include "Define.h"
#include "GraphicsItem.h"
#include <QPainter>
#include <QDebug>
#include "CalculateFeaturePoints.h"
#include "NameItem.h"

namespace Graphics
{
	class IndicateLineItemPrivate
	{
	public:
		/**
		 * @brief     constructor 
		 * @param     line[i]. line item
		 * @return    IndicateLineItemPrivate object
		 * @author    maguiwa (maguiwa520@163.com)
		 * @date 	  2024-9-3 13:05
		 */
		IndicateLineItemPrivate(IndicateLineItem * line)
            : _line(line)
		{

		}

        IndicateLineItem * _line{};

		/**
		 * @brief     Indicate Line Item Bounding Rect
		 * @author    maguiwa(maguiwa520@163.com)
		 * @date      2024-8-31 15:05
		 */
		QRectF _boundingRect{};

		/**
		 * @brief     Indicate Line Item From Graphics Item
		 * @author    maguiwa(maguiwa520@163.com)
		 * @date      2024-8-31 15:07
		 */
		GraphicsItem * _from{};

		/**
		 * @brief     Current Cursor Position
		 * @author    maguiwa(maguiwa520@163.com)
		 * @date      2024-8-31 15:08
		 */
		QPoint _cursorPt{};

		/**
		 * @brief     Feature Points
		 * @author    maguiwa(maguiwa520@163.com)
		 * @date      2024-8-31 17:21
		 */
		QList<QPoint> _featurePts{};

		/**
		 * @brief     pen indicate line painter used
		 * @author    maguiwa(maguiwa520@163.com)
		 * @date      2024-9-2 8:42
		 */
		QPen _pen{ QPen(QColor(56,56,56),1,Qt::PenStyle::DashLine) };

		/**
		 * @brief     in indicate line IndicateLine_ZTurning_Type . turning point distance to from graphics item
		 * @author    maguiwa(maguiwa520@163.com)
		 * @date      2024-8-31 17:23
		 */
		int _turningPointLength{ 40 };

		/**
		 * @brief     the size of the arrow
		 * @author    maguiwa(maguiwa520@163.com)
		 * @date      2024-9-2 9:22
		 */
		QSize _arrowSize{ QSize(14,10) };

		/**
		 * @brief     update feature points
		 * @return    void 
		 * @author    maguiwa (maguiwa520@163.com)
		 * @date 	  2024-9-2 10:34
		 */
		void updateFeaturePoints()
		{
			CalculateFeaturePoints calculator(QPoint(0, 0), _cursorPt);
			calculator.setGraphicsItemTopHeight(_from->boundingRect().height() / 2);
			calculator.setGraphicsItemBottomHeight(_from->boundingRect().height() / 2 + _from->namePart()->topBorderHeight() + _from->namePart()->boundingRect().height());
			calculator.setGraphicsItemWidth(_from->boundingRect().height() / 2);
			calculator.setArrowSize(_arrowSize);
			calculator.setTurningPointLength(_turningPointLength);
			_featurePts = calculator.featurePoints();
		}

		/**
		 * @brief     update indicate line item bounding box
		 * @return    void 
		 * @author    maguiwa (maguiwa520@163.com)
		 * @date 	  2024-9-2 11:33
		 */
		void updateBoundingBox()
		{
			if (_featurePts.isEmpty()) { return; }
			int xmin = _featurePts.first().x(), xmax = xmin, ymin = _featurePts.first().y(), ymax = ymin;

			for (auto pt : _featurePts)
			{
				xmin = std::min(pt.x(), xmin);
				xmax = std::max(pt.x(), xmax);
				ymin = std::min(pt.y(), ymin);
				ymax = std::max(pt.y(), ymax);
			}
            QPoint leftTop = QPoint(xmin, ymin);
            QPoint rightBottom = QPoint(xmax, ymax);
            _boundingRect = QRect(leftTop, rightBottom);
            qDebug() << leftTop << rightBottom;
		}
	};

	IndicateLineItem::IndicateLineItem(QGraphicsItem *parent /*= nullptr*/)
		: QGraphicsObject(parent)
		, _private(new IndicateLineItemPrivate(this))
	{

	}

	IndicateLineItem::~IndicateLineItem()
	{
		if (_private)
		{
			delete _private;
			_private = nullptr;
		}
	}

	QRectF IndicateLineItem::boundingRect() const
	{
        /// adjust bounding rect
        return _private->_boundingRect.adjusted(-2, -2, 2, 2);
	}

	void IndicateLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /* = nullptr */)
	{
		Q_UNUSED(option);
		Q_UNUSED(widget);

		painter->save();
		painter->setPen(_private->_pen);
		int ptNum = _private->_featurePts.size();
		for (int iCnt = 0; iCnt < ptNum - 1; ++iCnt)
		{
			painter->drawLine(_private->_featurePts[iCnt], _private->_featurePts[iCnt + 1]);
		}

		painter->restore();
	}

	void IndicateLineItem::setFromGraphicsItem(GraphicsItem * item)
	{
		_private->_from = item;
		_private->updateFeaturePoints();
	}

	Graphics::GraphicsItem * IndicateLineItem::fromGraphicsItem() const
	{
		return _private->_from;
	}

	void IndicateLineItem::setCursorPos(QPointF pos)
	{
		_private->_cursorPt = pos.toPoint();
		_private->updateFeaturePoints();
        prepareGeometryChange();
		_private->updateBoundingBox();
		update();
	}

}